<?php

class trickyCSS {
	
	function __construct(){
		
		// setup the default options, if you want different defaults, change them here
		
		// include the browser styles reset before all other content
		$this->options->reset = true;
		
		// send the contents of each include through the filters in the filters directory
		$this->options->filter = true;
		
		// include comments regarding file inclusion
		$this->options->comment = true;
		
		// say thanks via a comment at the very bottom of your final output
		$this->options->plug = false;
		
		// how many seconds to wait for a content refresh
		$this->options->cache = 900;
		
		// default constants files to include, comma seperated without file extensions
		$this->options->constants = '';
		
		// default stylesheets to include, comma seperated without file extensions
		$this->options->inc = '';		
		
		// check for option overrides in the query string
		$this->set_options();
		
		// get the browser information if available
		$this->browser = $this->get_browser();
		
		// if trickyCSS has been instantiated, and its not by an extension, do ouput
		if(__CLASS__ == get_class($this))
			$this->output();
		
	}
	
	function set_options(){
		
		foreach($this->options as $k => $v){
			if(isset($_GET[$k]))
				$this->options->{$k} = $_GET[$k];
		}
		
		$this->options->constants = explode(',', $this->options->constants);
		$this->inc = explode(',', $this->options->inc);
		
	}
	
	function output(){
		
		header('content-type:text/css');
		
		if($this->options->cache)
			header("Expires: ".gmdate("D, d M Y H:i:s", (time()+ $this->options->cache )) . " GMT");
		
		if($this->options->reset)
			$this->reset();

		if($this->options->constants)
			$this->constants();
			
		if(is_array($this->inc))
			$this->includes();
			
		if($this->options->plug)
			$this->plug();
			
	}
	
	function get_browser(){
		if(ini_get("browscap"))
    		return get_browser(null, true);
		else
			return false;
	}
	
	function reset(){
		
		$this->open_comment("css reset, via the king, http://meyerweb.com/eric/thoughts/2007/05/01/reset-reloaded/");
		echo 'html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,font,img,ins,kbd,q,s,samp,small,strike,strong,sub,sup,tt,var,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td{margin:0;padding:0;border:0;outline:0;font-weight:inherit;font-style:inherit;font-size:100%;font-family:inherit;vertical-align:baseline}:focus{outline:0}body{line-height:1;color:black;background:white}ol,ul{list-style:none}table{border-collapse:separate;border-spacing:0}caption,th,td{text-align:left;font-weight:normal}blockquote:before,blockquote:after,q:before,q:after{content:""}blockquote,q{quotes:""""}' . "\n";
		$this->close_comment("end of css reset");
		
	}
	
	function constants(){
		
		foreach($this->options->constants as $constants){
			$file = 'constants/' . $constants . '.php';
			if($this->file_check($file)){
				require_once($file);
				foreach($constants as $k => $v)
					$this->constants[$k] = $v;
			}
		}
		
	}
	
	function includes(){

		foreach($this->inc as $key => &$include){
			if(strpos($include, '*') !== FALSE && strpos($include, '..') === FALSE){
				if($add = $this->include_all($include))
					array_splice($this->inc, $key, 1, $add);
				else
					unset($this->inc[$key]);
			}
			elseif(!strpos($include, '.css'))
				$include .= '.css';
		}
		
		unset($include);
		
		foreach($this->inc as $include){
			$file = 'includes/' . $include;
			if($this->file_check($file)){
				$contents = file_get_contents($file);
				
				if($this->options->constants)
					foreach($this->constants as $key => $value)
						$contents = str_replace('$'.$key, $value, $contents);
				
				if($this->options->filter)
					$this->filters($contents);
				
				$this->open_comment("included from $file");
				echo $contents;
				$this->close_comment("end of $file");
			}
		}
		
	}
	
	function include_all($path){
		
		$path = str_replace('*','',$path);
		
		$location = './includes/' . $path;

		if(is_dir($location))
			if(is_array($dir_contents = scandir($location)))
				foreach($dir_contents as $file)
					if(is_file($location . $file)){
						$temp[] = $path . $file;
					}
					
		if(is_array($temp))
			return $temp;
		else
			return false;
			
	}
	
	function filters(&$contents){
		
		if($dh = opendir('filters'))
			while(($file = readdir($dh)) !== false)
				if($this->file_check('filters/' . $file)){
					// grab the files name
					$class = substr($file, 0, strrpos($file, '.'));
					require_once('filters/' . $file);
					// if the included file has the class we are looking for, instantiate it
					new $class($contents);
				}
		
	}
	
	// thank yous are always welcome
	function plug(){
		
		$this->open_comment("had some help from trickyCSS: http://trickeries.com/trickyCSS/");
		
	}
	
	// a quick file check, hopefully to stop anything dangerous, and make sure the file really exists	
	function file_check($file){
		
		// stuff we definitely don't want to see in a file name
		$bad = array("../","./","<!--","-->","<",">","'",'"','&','$','#','{','}','[',']','=',';','?',"%20","%22","%3c","%253c","%3e","%0e","%28","%29","%2528","%26","%24","%3f","%3b","%3d");
		
		// get rid of any of the above
		$file = stripslashes(str_replace($bad, '', $file));
		
		// make sure the file is really a file still
		return is_file($file);
		
	}
	
	// opening css comment, padded appropriately
	function open_comment($str){
		
		// check to see if comments are on
		if($this->options->comment)
			echo '/* ' . str_pad($str . " ", 77, '*') . "*/\n\n";
		
	}
	
	// closing css comment, padded appropriately
	function close_comment($str){
		
		// check to see if comments are on
		if($this->options->comment)
			echo "\n\n/* " . str_pad($str . " ", 77, '*') . "*/\n\n\n\n";
		
	}
	
}

new trickyCSS();

?>